package org.lc.oauth.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import lombok.RequiredArgsConstructor;
import org.lc.oauth.vo.LcUserDetails;
import org.lc.oauth.util.OAuth2EndpointUtils;
import org.lc.platform.base.constant.AuthConstant;
import org.lc.platform.base.domain.JwtUser;
import org.lc.platform.base.enums.LoginResultEnum;
import org.lc.platform.base.result.Result;
import org.lc.platform.redis.service.CacheService;
import org.lc.service.system.client.feign.IUserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**
 * 实现SpringSecurity获取用户信息接口
 *
 * @author lc
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LcUserDetailsServiceImpl implements UserDetailsService {
    private final IUserFeign userFeign;
    private final CacheService cache;
    /**
     * 密码最大尝试次数
     */
    @Value("${properties.oauth2.maxTryTimes:5}")
    private int maxTryTimes;

    @Value("${properties.common.init-system.default-role:''}")
    private String defaultRole;

    private void judgeFeignData(Result<?> res) {
        if (ObjUtil.isNull(res)) {
            OAuth2EndpointUtils.throwAuthError(LoginResultEnum.FEGIN_ABNORMAL);
        }
        if (!res.isSuccess()) {
            OAuth2EndpointUtils.throwAuthError(res.getMsg(), 40001);
        }
        if (ObjUtil.isNull(res.getData())) {
            OAuth2EndpointUtils.throwAuthError(LoginResultEnum.USER_NO_EXISTS);
        }
    }

    /**
     * 账号是否正常
     * 被锁定，禁用等
     */
    private void accountIsNormal(JwtUser user) {
        /* 从Redis获取账号密码错误次数 */
//        var key = AuthConstant.LOCK_ACCOUNT_PREFIX + user.getUserId();
        var key = user.getUserId() + ":account_lock";
        var lockTimes = this.cache.getInt(key);
        if (ObjUtil.isNotNull(lockTimes) && lockTimes >= maxTryTimes) {
            OAuth2EndpointUtils.throwAuthError(LoginResultEnum.LOGIN_COUNT_OVER);
        }
        /* 判断当前账号状态 */
        LoginResultEnum msg = null;
        if (user.getStatus() == 1) {
            msg = LoginResultEnum.STATUS_FREEZE;
        }
        if (user.isForbidden()) {
            msg = LoginResultEnum.ACCOUNT_DISABLED;
        }
        if (ObjUtil.isNotNull(msg)) {
            OAuth2EndpointUtils.throwAuthError(msg);
        }
    }

    @Override
    public LcUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        var clientId = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        /* 2、根据用户姓名采用远程调用登录接口 */
        Result<Object> result = userFeign.queryUserByAccount(username);
        /* 判断返回的feign数据是否有效 */
        this.judgeFeignData(result);
        JwtUser user = new JwtUser();
        BeanUtil.copyProperties(result.getData(), user, false);
        /* 判断返回的用户信息账号是否正常 */
        this.accountIsNormal(user);
        return new LcUserDetails(
                clientId,
                user.getUserId(),
                user.getPassword(),
                user.getUsername(),
                user.getNickName(),
                user.getRoles().contains(defaultRole),
                user.getRoles(),
                user.getAcls(),
                user.getApis()
        );
    }
}
